import { Directive, ElementRef, Input, OnInit, OnChanges, OnDestroy, SimpleChange } from '@angular/core';
import { debounce, countTransform, flowTransform } from '../utils';

const $: any = (window as any).$;
const echarts: any = (window as any).echarts;

/**
 * 趋势图,该组件在不同的场景下均可使用，应通过配置参数控制该组件处于什么场景
 * 参数结构如下：
 * chartOptions: any = {
 *     events: {click: v => {}, dblclick: v => {}},                           // 事件，依次类推，可以添加任何echarts支持的事件，默认为空
 *     interval: number,                                                      // 折线图横轴刻度标签间隔几个显示，默认为0全部显示
 *     title: '',                                                             // 折线图标题,标题在左侧。默认为空
 *     formatValue: 'flow',                                                   // 1.可以取如下两个值：
 *                                                                                    flow：(bps/pps)数据处理('K/M/G/T');
 *                                                                                    format：处理为万/亿。
 *                                                                            // 2.不设置formatValue时，默认不处理数据;
 *     axisData: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
 *     seriesData: {
 *         'SYN FLOOD': [0, 132, 101, 134 * Math.random() * 5, 90, 10, 0],
 *         'UDP FLOOD': [0, 132, 101, 134 * Math.random() * 5, 90, 10, 0],
 *         'NTP REFLECTION FLOOD': [0, 132, 101, 134 * Math.random() * 5, 90, 10, 0],
 *     },
 *     grid: {},                                                              //图表组件离容器四面的距离，可选
 *     legend: {}                                                             //图例组件的配置，可选，如果传入则按照echarts
 *                                                                              legend接受的参数来配置
 *     containerWifth: 0.5,                                                   // 1表示div为100%，0.5表示50%
 *     theme: 'dark'  默认为非首页主题，可以不设置，首页设置为'dark'
 *     legendRight: '40' 图例离趋势图右侧的距离，默认可以不设置，图例布局为center
 *     formatter: function,                                                  // 自定义格式化悬浮框信息
 *     yMinInterval: 0,                                                      // 设置y轴坐标轴最小间隔大小，设置成1保证坐标轴分割刻度显示成整数
 *     noArea: true/false,                                                   // 默认可以不设置，表示面积图(或者noArea：false)；为true时，表示非面积图
 *     rotate: 30,                                                           // x轴的label旋转度数
 * };
 */
@Directive({
    selector: '[appEchartsLine]'
})
export class EchartsLineDirective implements OnInit, OnChanges, OnDestroy {
    @Input() appEchartsLine: any; // 图表配置参数
    oldSelected: any;
    chart: any; // 图表本身
    resizeNamespace: string = 'resize.' + Date.now(); // 图表绑定到resize事件，需要一个命名空间

    $elem: any;
    constructor(private el: ElementRef) {
        this.$elem = $(el.nativeElement);
    }

    renderChart() {
        const op: any = {
            title: {
                text: '',
                textStyle: { fontSize: 14 },
                padding: [0, 0, 0, 0],
                textBaseline: 'top'
            },
            color: [],
            tooltip: {
                trigger: 'axis',
                backgroundColor: 'rgba(0, 0, 0, 0.7)',
                padding: [15, 20, 15, 20],
                textStyle: {
                    fontSize: '12'
                },
                formatter: this.appEchartsLine.formatter || null // 自定义悬浮框信息
            },
            legend: {
                textStyle: {
                    color: '#858585'
                },
                right: 'auto',
                icon: 'circle',
                data: [],
                itemHeight: 10,
            },
            grid: {
                left: '4%',
                right: '4%',
                top: 50,
                bottom: 35,
                containLabel: true
            },
            xAxis: [{
                axisLine: { lineStyle: { color: '', width: 0 } },
                axisLabel: {
                    rotate: 30,
                    // interval: 0,
                    margin: 9,
                    textStyle: { color: '#858585' }
                },
                type: 'category',
                boundaryGap: false,
                data: []
            }],
            yAxis: [{
                name: '',
                nameTextStyle : { color: '#858585'},
                axisLine: { lineStyle: { color:'', width: 0 } },
                axisLabel: {
                    formatter: function(val) {
                        return val;
                    },
                    interval: 0,
                    margin: 8,
                    textStyle: { color: '#858585' }
                },
                splitLine: {
                    lineStyle: {
                        color: '#e5e5e5'
                    }
                },
                type: 'value'
            }],
            series: []
        };

        op.legend.data = Object.keys(this.appEchartsLine.seriesData);
        const series = [];

        let noArea = this.appEchartsLine.noArea;
        op.legend.data.forEach((v, i) => {
            series.push({
                name: v,
                type: 'line',
                smooth: true,
                areaStyle: { normal: { opacity: (noArea) ? 0 : 0.2 } }, // 面积图
                data: this.appEchartsLine.seriesData[v]
            });
        });
        op.series = series;
        op.color = ['#0099FF', '#66CC33', '#00CCCC', '#FFCC33', '#f8c300', '#FF6699', '#68b92e', '#0093dd', '#5dcdf5',
            '#e77817', '#667ab3', '#9866b4', '#36b684', '#da251d', '#68b920', '#3bb3c2', '#56c9a9', '#c55cd5', '#da307c'];
        op.xAxis[0].data = this.appEchartsLine.axisData;

        // 图标题显示在左侧
        let text = (this.appEchartsLine.title) ? (this.appEchartsLine.title) : ' ';
        if (text !== ' ') {
            op.title.text = text;
            op.grid.left = '5%';
        }

        // 图例配置
        if (this.appEchartsLine.legend) {
            for (const key in this.appEchartsLine.legend) {
                op.legend[key] = this.appEchartsLine.legend[key];
            }
        }
        // 图表组件离容器四周的距离
        if (this.appEchartsLine.grid) {
            for (const key in this.appEchartsLine.grid) {
                op.grid[key] = this.appEchartsLine.grid[key];
            }
            if (!this.appEchartsLine.grid.top) {
                let legendWifth = 6;
                if (this.appEchartsLine.containerWifth) {
                    legendWifth *= this.appEchartsLine.containerWifth;
                }
                if (op.legend.data.length > legendWifth * 3) {
                    op.grid.top = 100;
                } else if (op.legend.data.length > legendWifth * 2) {
                    op.grid.top = 85;
                } else if (op.legend.data.length > legendWifth) {
                    op.grid.top = 70;
                }
            }
        }

        // 主题色
        if (this.appEchartsLine.theme === 'dark') {
            op.yAxis[0].splitLine.lineStyle.color = '#656565';
            op.legend.textStyle.color = '#ccc';
            op.legend.inactiveColor = '#656565';
        }
        // 设置图例距右侧的距离 string|number
        if (this.appEchartsLine.legendRight !== undefined) {
            op.legend.right = this.appEchartsLine.legendRight;
        }
        // 设置调色盘颜色列表
        if (this.appEchartsLine.color) {
            op.color = this.appEchartsLine.color;
        }

        // category轴间隔几个显示
        if (this.appEchartsLine.interval != null) {
            op.xAxis[0].axisLabel.interval = this.appEchartsLine.interval;
        }

        // 格式化tooltip展示的bps/pps流量数据以及y轴数据
        if (this.appEchartsLine.formatValue === 'format' || this.appEchartsLine.formatValue === 'flow') {
            op.tooltip['formatter'] = (val) => {
                let length = val.length;
                let res = '';
                res += val[0].name + ':<br/>';
                for (let i = 0; i < length; i++) {
                    res += '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:' + val[i].color + '"></span>' + val[i].seriesName + ': '; // 每项添加圆形小图例
                    let number = parseFloat(val[i].value);
                    let str = '';
                    if (this.appEchartsLine.formatValue === 'format') {
                        str = countTransform(number);
                    }
                    if (this.appEchartsLine.formatValue === 'flow') {
                        if (this.appEchartsLine.formatUnit == undefined){
                            str = flowTransform(number);
                        }else{
                            str = flowTransform(number, this.appEchartsLine.formatUnit);
                        }

                    }
                    res += str + '<br/>';
                }
                return res;
            };

            op.yAxis[0].axisLabel.formatter = (val) => {
                if (this.appEchartsLine.formatValue === 'flow') {
                    if (this.appEchartsLine.formatUnit == undefined) {
                        val = flowTransform(val);
                    }else{
                        val = flowTransform(val, this.appEchartsLine.formatUnit);
                    }

                }
                if (this.appEchartsLine.formatValue === 'format') {
                    val = countTransform(val);
                }
                return val;
            };
        }
        // 设置x轴文字倾斜
        if (this.appEchartsLine.xRotate) {
            op.xAxis[0].axisLabel.rotate = this.appEchartsLine.xRotate;
        }
        // 自定义悬浮层信息
        if (this.appEchartsLine.formatter) {
            op.tooltip['formatter'] = this.appEchartsLine.formatter;
        }

        if (this.appEchartsLine.rotate !== undefined) {
            op.xAxis[0].axisLabel.rotate = this.appEchartsLine.rotate;
        }

        if (this.appEchartsLine.yMinInterval) {
            op.yAxis[0].minInterval = this.appEchartsLine.yMinInterval;
        }
        if (this.appEchartsLine.yAxisName) {
            op.yAxis[0].name = this.appEchartsLine.yAxisName;
        }

        //图例标记的高度
        if (this.appEchartsLine.lengendItemHeight !== undefined) {
            op.legend.itemHeight = this.appEchartsLine.lengendItemHeight;
        }

        //为特殊图例添加横向滚动
        if(this.appEchartsLine.isSpecLine){
            op.legend.type="scroll",
            op.legend.pageButtonPosition= 'end',
            op.legend.pageIconSize= 10,
            op.legend.animation= true,
            op.legend.top= 2,
            op.legend.left= 20,
            op.legend.itemGap= 15,
            op.legend.itemWidth= 8
        }

        let selected = this.oldSelected;

        this.chart.clear();

        op.legend.selected = {};
        for (let key in selected) {
            if (selected.hasOwnProperty(key)) {
                if (selected[key] === false) {
                    op.legend.selected[key] = false;
                }
            }
        }

        this.chart.setOption(op, false);
    }

    // 初始化画布，绑定resize事件
    initChart() {
        this.chart = echarts.init(this.el.nativeElement);
        const resize = this.chart.resize;
        const resizeNamespace = this.resizeNamespace;
        $(window).off(resizeNamespace);
        $(window).on(resizeNamespace, debounce(resize, 200, false));
        if (this.appEchartsLine.events) {
            for (const prop in this.appEchartsLine.events) {
                this.chart.on(prop, this.appEchartsLine.events[prop]);
            }
        }
    }

    // 解除resize
    relieve() {
        const resizeNamespace = this.resizeNamespace;
        $(window).off(resizeNamespace);
        if (this.chart) {
            this.chart.dispose();
        }
    }

    ngOnInit() {}

    ngOnChanges(changes: {
        [propKey: string]: SimpleChange
    }) {
        const options = changes['appEchartsLine'];
        if (options && options.previousValue !== options.currentValue && options.currentValue) {
            this.relieve();
            if (this.chart) {
                /**
                 * 这里是将上一次的图例选择状态予以保留，为啥搞得这么复杂呢，其实我去掉 this.chart.clear() 这一行就可以了
                 * 我是为了尽量减少风险,我害怕呀
                 */
                let oldOp = this.chart.getOption();
                this.oldSelected = oldOp && oldOp.legend[0].selected || {};
            }
            this.initChart();
            this.renderChart();
        }
    }

    ngOnDestroy() {
        this.relieve();
    }

    resize(height, width) {
        if (this.chart) {
            this.chart.resize({ width: width, height: height });
        }
    }
}
